<template>
  <div class="panel-box">
    <el-container>
      <el-aside>
        <div class="top-bar">
          <el-button type="primary" @click="editGzfl()">新增</el-button>
        </div>
        <div class="inner-box">
          <el-input v-model="gzflFilterGjz" placeholder="规则分类名称/规则分类标识"></el-input>
          <div v-for="item in gzflList"
               v-show="item.gzflbs.indexOf(gzflFilterGjz)>-1||item.gzflmc.indexOf(gzflFilterGjz)>-1"
               :key="item.gzflbm" :class="{active:currGzflbm===item.gzflbm}"
               class="list-item" @click="queryGzdyListByGzfl(item)">
            <div class="mc-box">
              <div :title="item.gzflmc">{{ item.gzflmc }}</div>
              <div :title="item.gzflbs" style="font-size: 12px;color:red;">{{ item.gzflbs }}</div>
            </div>
            <div class="btn-box" @click.stop="{}">
              <div class="btn edit-btn" title="编辑" @click="editGzfl(item)"></div>
              <div class="btn delete-btn" title="删除" @click="preDel(delGzfl,item)"></div>
            </div>
          </div>
        </div>
      </el-aside>
      <el-divider direction="vertical"></el-divider>
      <el-main>
        <div class="top-bar">
          <el-button type="danger" v-show="selectedCount" @click="deleteSelectedGz">批量删除</el-button>
          <el-button type="primary" v-show="selectedCount" @click="copySelectedGz">批量复制</el-button>
          <el-button type="primary" @click="importGzVisible=true">导入</el-button>
          <el-button type="primary" @click="editGzdy()">新增</el-button>
          <el-button type="primary" @click="startPx()">排序</el-button>
        </div>
        <el-table
            :data="gzdyList"
            stripe
            ref="gzTable"
            height="calc(100% - 28px)"
            @selection-change="handleGzdyListSelectionChange"
            style="width: 100%">
          <el-table-column
              type="selection"
              width="50">
          </el-table-column>
          <el-table-column
              label="序号"
              type="index"
              width="50">
          </el-table-column>
          <el-table-column
              label="规则名称">
            <template slot-scope="{row}">
              <el-link type="primary" @click="designGz(row)">{{ row.gzmc }}</el-link>
            </template>
          </el-table-column>
          <el-table-column
              label="规则描述"
              prop="gzms"
              show-overflow-tooltip>
          </el-table-column>
          <el-table-column
              label="规则编码"
              prop="gzbm"
              width="250px">
          </el-table-column>
          <el-table-column
              label="是否启用"
              prop="sfqy"
              align="center"
              width="85px">
            <template slot-scope="{row}">
              <el-checkbox @change="setGzdyQyzt(row)" :value=" row.sfqy === 'Y'"></el-checkbox>
            </template>
          </el-table-column>
          <el-table-column
              label="创建时间"
              prop="cjsj"
              width="135px">
          </el-table-column>
          <el-table-column
              label="操作"
              width="210px">
            <template slot-scope="{row}">
              <el-button @click="copyGz(row)">复制</el-button>
              <el-button @click="editGzdy(row)">编辑</el-button>
              <el-button type="danger" @click="preDel(delGzdy,row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-main>
    </el-container>

    <xj-dialog :title="(gzflForm.gzflbm?'编辑':'新增')+'规则分类'"
               :visible="addGzflDialogVisible"
               height="100vh">
      <el-form :model="gzflForm" style="height:calc(100% - 18px)">
        <el-form-item v-show="!gzflForm.gzflbm" label="分类来源" label-width="120px">
          <el-radio-group v-model="gzflForm.gzflly">
            <el-radio-button label="0">自定义</el-radio-button>
            <el-radio-button label="sjmxTable">数据模型</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <div v-show="gzflForm.gzflly==='0'">
          <el-form-item label="规则分类名称" label-width="120px">
            <el-input v-model="gzflForm.gzflmc" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="规则分类标识" label-width="120px">
            <el-input v-model="gzflForm.gzflbs" autocomplete="off"></el-input>
          </el-form-item>
        </div>
        <div v-show="gzflForm.gzflly==='sjmxTable'" style="height:100%">
          <el-form-item label="关键字" label-width="120px">
            <el-input v-model="filterGjz" placeholder="规则分类名称/规则分类标识"></el-input>
          </el-form-item>
          <el-table
              ref="sjmxTable"
              :data="sjmxDataShow"
              height="calc(100% - 50px)"
              style="width: 100%">
            <el-table-column
                type="selection"
                :selectable="isAddGzfl"
                width="50">
            </el-table-column>
            <el-table-column
                label="序号"
                type="index"
                width="50">
            </el-table-column>
            <el-table-column
                prop="gzflmc"
                label="规则分类名称">
            </el-table-column>
            <el-table-column
                prop="gzflbs"
                label="规则分类标识"
                width="240">
            </el-table-column>
          </el-table>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="handleAddGzflBtnClick(false)">取消</el-button>
        <el-button type="primary" @click="handleAddGzflBtnClick(true)">确定</el-button>
      </div>
    </xj-dialog>
    <xj-dialog title="选择规则分类" :visible="!!selectedGzbmList.length">
      <div style="display:grid;grid-template-columns: repeat(auto-fit,150px);grid-gap: 10px;grid-column-gap: 10px">
        <el-tag
            style="text-align: center"
            :effect="selectGzfl[gzfl.gzflbm]?'dark':'plain'"
            v-for="gzfl in gzflList"
            @click="toggleSelect(gzfl)"
            size="medium">{{ gzfl.gzflmc }}
        </el-tag>
      </div>
      <template slot="footer">
        <el-button @click="handleCopyGzBtnClick(false)">取消</el-button>
        <el-button @click="handleCopyGzBtnClick(true)" type="primary">确定</el-button>
      </template>
    </xj-dialog>
    <xj-dialog title="规则排序" :visible="pxVisible" width="500px">
      <transition-group tag="div">
        <div class="list-item canmove"
             :class="{
              over:overGzbm+pos===gzdy.gzbm+'over',
              'over-top':overGzbm+pos===gzdy.gzbm+'top',
              'over-bottom':overGzbm+pos===gzdy.gzbm+'bottom',
           }"
             draggable
             v-for="(gzdy,idx) in pxGz"
             @dragstart="handleDragStart($event,gzdy)"
             @dragover="handleDragOver($event,gzdy)"
             @drop="handleDrop($event,gzdy)"
             :key="gzdy.gzbm">
          <span style="color: red;margin-right: 10px">{{ gzdy.yssx + 1 }}</span>
          <span style="color: red;margin-right: 10px;font-family: Consolas,serif">---></span>
          <span style="color: red;margin-right: 10px">{{ idx + 1 }}</span>
          {{ gzdy.gzmc }}
        </div>
      </transition-group>
      <template slot="footer">
        <el-button @click="handlePxClick(false)">取消</el-button>
        <el-button @click="handlePxClick(true)" type="primary">确定</el-button>
      </template>
    </xj-dialog>
    <xj-dialog title="请选择导入的规则" :visible="importGzVisible">
      <el-cascader-panel :props="props" v-model="selectedImportGzdyList"></el-cascader-panel>
      <div slot="footer">
        <el-button @click="handleImportGzdyBtnClick(false)">取消</el-button>
        <el-button type="primary" @click="handleImportGzdyBtnClick(true)">确定</el-button>
      </div>
    </xj-dialog>
    <xj-dialog :title="(gzdyForm.gzbm?'编辑':'新增')+'规则定义'" :visible="editGzdyVisible">
      <el-form :model="gzdyForm" label-width="120px">
        <div class="form-box">
          <el-form-item label="规则名称">
            <el-input v-model="gzdyForm.gzmc"></el-input>
          </el-form-item>
          <el-form-item label="规则描述">
            <el-input v-model="gzdyForm.gzms"></el-input>
          </el-form-item>

          <el-form-item :label="item.mc" v-for="item in xmItem.xmpz" :key="item.bm">
            <el-radio-group v-model="gzdyForm.gzpz[item.bm]" v-if="item.lx==='radio-button'">
              <el-radio-button :label="_item.value" v-for="_item in item.options">{{ _item.label }}
              </el-radio-button>
            </el-radio-group>
            <el-select v-model="gzdyForm.gzpz[item.bm]" v-if="item.lx==='select'" style="width: 100%">
              <el-option :label="_item.label" :value="_item.value" v-for="_item in item.options">{{ _item.label }}
              </el-option>
            </el-select>
            <el-input v-model="gzdyForm.gzpz[item.bm]" v-if="item.lx==='input'"></el-input>
          </el-form-item>

        </div>
      </el-form>
      <div slot="footer">
        <el-button @click="handleEditGzdyBtnClick(false)">取消</el-button>
        <el-button type="primary" @click="handleEditGzdyBtnClick(true)">确定</el-button>
      </div>
    </xj-dialog>
  </div>
</template>

<script>
import commonMixins from "@/mixins/commonMixins";
import XjDialog from "@/components/XjDialog";
import sjmxData from '../data/sjmxData.json'

export default {
  name: "Gzgl",
  components: {XjDialog},
  mixins: [commonMixins],
  data() {
    return {
      sjmxData,
      gzflList: [],
      addGzflDialogVisible: false,
      importGzVisible: false,
      editGzdyVisible: false,
      gzflForm: {
        gzflbm: '',
        gzflmc: '',
        gzflbs: '',
        gzflly: '0'
      },
      gzdyForm: {
        gzbm: '',
        gzpz: {}
      },
      currGzflbm: '',
      gzdyList: [],
      selectedGzbmList: [],
      selectedImportGzdyList: [],
      props: {
        lazy: true,
        multiple: true,
        lazyLoad: async (node, resolve) => {
          const {level, value} = node;
          if (level === 0) {
            let xmList = await this.$api.queryXmListByRybm({rybm: this.yhxx.rybm})
            resolve(xmList.filter(item => item.xmbm !== this.xmItem.xmbm).map(item => {
              return {
                label: item.xmmc,
                value: item.xmbm,
                leaf: false
              }
            }))
          } else if (level === 1) {
            // 加载规则分类
            let gzflList = await this.$api.queryGzflListByXmbm({xmbm: value})
            resolve(gzflList.map(item => {
              return {
                label: item.gzflmc,
                value: item.gzflbm,
                leaf: false
              }
            }))
          } else if (level === 2) {
            // 加载规则定义
            let gzdyList = await this.$api.queryGzdyListByGzflbm({gzflbm: value})
            resolve(gzdyList.map(item => {
              return {
                label: item.gzmc,
                value: item.gzbm,
                leaf: true
              }
            }))
          } else {
            resolve([])
          }
        },
      },

      pxGz: [],
      dragGzdy: null,
      overGzbm: '',
      pos: '',
      pxVisible: false,
      filterGjz: '',
      gzflFilterGjz: '',
      selectGzfl: {},
      selectedCount: 0,
    }
  },
  computed: {
    sjmxDataShow() {
      return this.sjmxData.filter(item => {
        let b = item.mxbm.indexOf(this.filterGjz) > -1
        if (b) return true
        return item.mxmc.indexOf(this.filterGjz) > -1
      }).map(item => {
        return {
          gzflmc: item.mxmc,
          gzflbs: item.mxbm,
        }
      })
    }
  },
  mounted() {
    this.queryGzflListByXmbm()
    this.$store.dispatch("loadMxstgxList")
  },
  methods: {
    async handleEditGzdyBtnClick(isConfirm) {
      if (isConfirm) {
        let gzdy = {
          gzbm: this.gzdyForm.gzbm,
          gzmc: this.gzdyForm.gzmc,
          gzms: this.gzdyForm.gzms,
          gzflbm: this.gzdyForm.gzflbm,
          gzpz: JSON.stringify(this.gzdyForm.gzpz)
        }
        if (this.gzdyForm.gzbm) {
          try {
            await this.$api.updateGzdy(gzdy)
            this.$message({message: "修改成功", type: 'success'})
          } catch (e) {
            this.$message({message: e.message, type: 'error'})
            return
          }
        } else {
          try {
            await this.$api.addGzdy(gzdy)
            this.$message({message: "添加成功", type: 'success'})
          } catch (e) {
            this.$message({message: e.message, type: 'error'})
            return
          }
        }
        this.queryGzdyList()
      }
      this.editGzdyVisible = false

    },
    async handleImportGzdyBtnClick(isConfirm) {
      if (isConfirm) {
        let errArr = []
        for (let selectedImportGzdyListElement of this.selectedImportGzdyList) {
          try {
            let gzbm = selectedImportGzdyListElement[2]
            await this.copyGzToGzfl(gzbm, this.currGzflbm)
          } catch (e) {
            errArr.push(e.message)
          }
        }
        this.queryGzdyList()
        if (errArr.length) {
          this.$message({message: `部分规则导入失败：${errArr.join(",")}`, type: 'warning'})
        } else {
          this.$message({message: "导入成功", type: 'success'})
        }
      }
      this.importGzVisible = false
      this.selectedImportGzdyList = []
    },
    handleGzdyListSelectionChange(selection) {
      this.selectedCount = selection.length
    },
    toggleSelect(gzfl) {
      this.$set(this.selectGzfl, gzfl.gzflbm, !this.selectGzfl[gzfl.gzflbm])
    },
    isAddGzfl(row, idx) {
      return !this.gzflList.find(item => item.gzflbs === row.gzflbs)
    },
    startPx() {
      this.pxGz = this.gzdyList.map((item, idx) => ({gzbm: item.gzbm, gzmc: item.gzmc, yssx: idx}))
      this.pxVisible = true
    },
    handleDragStart(e, gzdy) {
      this.dragGzdy = gzdy
    },
    handleDragOver(e, gzdy) {
      let el = e.target
      do {
        if (el.classList.contains('list-item')) break
      } while ((el = el.parentNode))
      let totalHeight = el.offsetHeight
      let y = e.offsetY
      this.overGzbm = gzdy.gzbm
      if (y <= totalHeight / 4) {
        this.pos = "top"
      } else if (y <= totalHeight * 3 / 4) {
        this.pos = "over"
      } else {
        this.pos = "bottom"
      }
      e.preventDefault()
    },
    handleDrop(e, gzdy) {
      if (this.dragGzdy.gzbm === gzdy.gzbm) {
        this.pos = ''
        return
      }
      let gzList = this.pxGz
      let oldIdx = gzList.findIndex(item => item.gzbm === this.dragGzdy.gzbm)
      if (oldIdx !== -1) {
        if (this.pos === 'top') {
          // 删除旧的
          let oldItem = gzList[oldIdx]
          gzList.splice(oldIdx, 1)
          // 插入到新位置
          let newIdx = gzList.findIndex(item => item.gzbm === gzdy.gzbm)
          gzList.splice(newIdx, 0, oldItem)
        } else if (this.pos === "over") {
          let oldItem = gzList[oldIdx]

          let newIdx = gzList.findIndex(item => item.gzbm === gzdy.gzbm)
          let newItem = gzList[newIdx]

          // 交换两个
          gzList.splice(oldIdx, 1, newItem)
          gzList.splice(newIdx, 1, oldItem)
        } else {
          // 删除旧的
          let oldItem = gzList[oldIdx]
          gzList.splice(oldIdx, 1)
          // 插入到新位置
          let newIdx = gzList.findIndex(item => item.gzbm === gzdy.gzbm)
          gzList.splice(newIdx + 1, 0, oldItem)
        }
      }
      this.pos = ''
    },
    async handlePxClick(isConfirm) {
      if (isConfirm) {
        try {
          let params = this.pxGz.map((item, idx) => ({gzbm: item.gzbm, px: idx}))
          await this.$api.sortGzdy(params)
          this.queryGzdyList()
        } catch (e) {
          return this.$message({message: e.message, type: 'error'})
        }
      }
      this.pxVisible = false
    },
    async queryGzflListByXmbm() {
      try {
        this.gzflList = await this.$api.queryGzflListByXmbm({xmbm: this.xmItem.xmbm})
        if (!this.gzflList.length) return
        let gzflbm = mySessionStorage.getItem('gzflbm')
        let gzfl = this.gzflList.find(item => item.gzflbm === gzflbm)
        if (gzfl == null) gzfl = this.gzflList[0]
        this.queryGzdyListByGzfl(gzfl)
      } catch (e) {
        this.$message({message: e.message, type: 'error'})
      }
    },
    async delGzfl(gzfl) {
      try {
        await this.$api.deleteGzfl({gzflbm: gzfl.gzflbm})
        this.queryGzflListByXmbm()
        this.handleAddGzflBtnClick(false)
      } catch (e) {
        this.$message({message: e.message, type: 'error'})
      }
    },
    async handleAddGzflBtnClick(isConfirm) {
      if (isConfirm) {
        // 进行保存
        try {
          if (this.gzflForm.gzflbm) {
            await this.$api.updateGzfl({
              gzflbm: this.gzflForm.gzflbm,
              gzflbs: this.gzflForm.gzflbs,
              gzflmc: this.gzflForm.gzflmc
            })
          } else {
            if (this.gzflForm.gzflly === '0') {
              await this.$api.addGzfl({
                gzflbs: this.gzflForm.gzflbs,
                gzflmc: this.gzflForm.gzflmc,
                xmbm: this.xmItem.xmbm
              })
            } else {
              // 批量添加
              let table = this.$refs[this.gzflForm.gzflly]
              let selection = table.selection
              for (let selectionElement of selection) {
                await this.$api.addGzfl({
                  gzflbs: selectionElement.gzflbs,
                  gzflmc: selectionElement.gzflmc,
                  xmbm: this.xmItem.xmbm
                })
              }
            }
          }
          this.queryGzflListByXmbm()
        } catch (e) {
          this.$message({message: e.message, type: 'error'})
          return
        }
      }
      this.addGzflDialogVisible = false
    },
    editGzfl(gzfl) {
      gzfl = gzfl || {}
      this.gzflForm = {
        gzflly: "0",
        gzflbm: gzfl.gzflbm, gzflmc: gzfl.gzflmc, gzflbs: gzfl.gzflbs
      }
      this.addGzflDialogVisible = true
    },
    async queryGzdyListByGzfl(gzfl) {
      this.currGzflbm = gzfl.gzflbm
      mySessionStorage.setItem("gzflbm", this.currGzflbm)
      this.queryGzdyList()
    },
    async queryGzdyList() {
      this.gzdyList = await this.$api.queryGzdyListByGzflbm({gzflbm: this.currGzflbm})
    },
    async delGzdy(gzdy) {
      try {
        let errArr = []
        if (Array.isArray(gzdy)) {
          for (let gzdyElement of gzdy) {
            try {
              await this.$api.deleteGzdy({gzbm: gzdyElement.gzbm})
            } catch (e) {
              errArr.push(e.message)
            }
          }
        } else {
          await this.$api.deleteGzdy({gzbm: gzdy.gzbm})
        }
        if (errArr.length) {
          this.$message({message: `部分删除失败：${errArr.join(",")}`, type: 'warning'})
        } else {
          this.$message({message: "删除成功", type: 'success'})
        }
      } catch (e) {
        this.$message({message: e.message, type: 'error'})
      }
      this.queryGzdyList()
    },
    async setGzdyQyzt(gzdy) {
      try {
        const pam = {gzbm: gzdy.gzbm, sfqy: 'Y'}
        if (gzdy.sfqy === 'Y') pam.sfqy = "N"

        await this.$api.setGzdyQyzt(pam)
        this.$message({message: "设置状态成功", type: 'success'})
        this.queryGzdyList()
      } catch (e) {
        this.$message({message: e.message, type: 'error'})
      }
    },
    async designGz(gzdy) {
      mySessionStorage.setItem("gzdy-item", gzdy)
      this.$router.push(`/design`)
    },
    copySelectedGz() {
      let selection = this.$refs.gzTable.selection
      this.selectedGzbmList = selection.map(item => item.gzbm)
    },
    deleteSelectedGz() {
      let selection = this.$refs.gzTable.selection
      this.preDel(this.delGzdy, selection, `即将删除${selection.length}条规则，删除将不可恢复，是否删除？`)
    },
    editGzdy(gzdy) {
      if (!gzdy) {
        let gzflbm = mySessionStorage.getItem("gzflbm")
        gzdy = {
          gzbm: '',
          gzmc: '',
          gzms: '',
          gzpz: {},
          gzflbm,
        }
        for (const xmpzElement of this.xmItem.xmpz) {
          gzdy.gzpz[xmpzElement.bm] = xmpzElement.mrz
        }
      } else {
        gzdy = {
          ...gzdy,
          gzpz: JSON.parse(gzdy.gzpz || '{}')
        }
      }
      for (let gzpzKey in gzdy.gzpz) {
        let pzItem = this.xmItem.xmpz.find(item => item.bm === gzpzKey)
        if (!pzItem) {
          delete gzdy.gzpz[gzpzKey]
        }
      }
      this.gzdyForm = gzdy
      this.editGzdyVisible = true
    },
    copyGz(gzdy) {
      this.selectedGzbmList = [gzdy.gzbm]
    },
    copyGzToGzfl(gzbm, gzflbm) {
      return this.$api.copyGz({gzflbm: gzflbm, gzbm: gzbm})
    },
    async handleCopyGzBtnClick(isConfirm) {
      if (isConfirm) {
        try {
          for (let selectGzflKey in this.selectGzfl) {
            if (this.selectGzfl[selectGzflKey]) {
              for (let selectedGzbmListElement of this.selectedGzbmList) {
                await this.copyGzToGzfl(selectedGzbmListElement, selectGzflKey)
              }
            }
          }
        } catch (e) {
          return this.$message({message: e.message, type: 'error'})
        }
        this.queryGzdyList()
        this.$message({message: '规则复制完成', type: 'success'})
      }
      // this.selectGzflbm = null
      this.selectedGzbmList = []
    }
  }
}
</script>
